package com.brillilab.service.core.space.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.constant.LetterConstant;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.dao.mapper.inventory.ReagentInventoryMapper;
import com.brillilab.dao.mapper.space.BoxGridMapper;
import com.brillilab.dao.mapper.space.BoxMapper;
import com.brillilab.dao.mapper.space.PanelGridUsedMapper;
import com.brillilab.dao.mapper.space.PanelMapper;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.space.SpaceTypeEnum;
import com.brillilab.domain.po.inventory.ReagentInventory;
import com.brillilab.domain.po.space.Box;
import com.brillilab.domain.po.space.BoxGrid;
import com.brillilab.domain.po.space.PanelGridUsed;
import com.brillilab.domain.vo.inventory.BoxMove;
import com.brillilab.domain.vo.lab.LabMemberVo;
import com.brillilab.domain.vo.space.BoxGridWithReagentType;
import com.brillilab.domain.vo.space.BoxVo;
import com.brillilab.service.core.space.IBoxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wuzhiyu
 * @Title: BoxServiceImpl
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/159:09
 */
@Service
@Transactional
public class BoxServiceImpl implements IBoxService {


    @Autowired
    private BoxMapper boxMapper;
    @Autowired
    private BoxGridMapper boxGridMapper;
    @Autowired
    private PanelGridUsedMapper panelGridUsedMapper;
    @Resource
    private ReagentInventoryMapper reagentInventoryMapper;

    @Override
    public boolean delete(Long spaceId, SpaceTypeEnum spaceTypeEnum) {
        LambdaQueryWrapper<Box> wrapper = new LambdaQueryWrapper<>();
        switch (spaceTypeEnum) {
            case ROOM:
                wrapper.eq(Box::getRoomId, spaceId);
                break;
            case DEVICE:
                wrapper.eq(Box::getDeviceId, spaceId);
                break;
            case PANEL:
                wrapper.eq(Box::getPanelId, spaceId);
                break;
            case BOX:
                wrapper.eq(Box::getId, spaceId);
                break;
        }
        Box box = new Box();
        box.setIsDelete(1);
        return boxMapper.update(box, wrapper) > 0;
    }

    @Override
    public boolean deleteByPanelIdList(List<Long> idList) {
        LambdaQueryWrapper<Box> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Box::getPanelId, idList);
        Box box = new Box();
        box.setIsDelete(1);
        return boxMapper.update(box, wrapper) > 0;
    }

    @Override
    public Box add(Box box) {
        if (box.getColumns().equals(1) && box.getRows().equals(1)) {
            //无分隔试剂盒格子规格为box.sepc=0
            box.setSpec(0);
        }
        if (!StringUtils.isEmpty(box.getUserReagentType())) {
            box.setUserReagentType("," + box.getUserReagentType() + ",");
        }
        boxMapper.insert(box);
        List<BoxGrid> gridList = new ArrayList<>();
        for (int y = 0; y < box.getRows(); y++) {
            for (int i = 1; i <= box.getColumns(); i++) {
                BoxGrid bg = new BoxGrid();
                bg.setBoxColor(box.getBoxColor());
                bg.setBoxId(box.getId());
                bg.setColumnNo(i);
                bg.setRowNo(LetterConstant.LetterUpperList[y]);
                bg.setDeviceId(box.getDeviceId());
                bg.setDeviceIndex(box.getDeviceIndex());
                bg.setIsFill(0);
                bg.setLabId(box.getLabId());
                bg.setLabMemberId(box.getLabMemberId());
                bg.setPanelId(box.getPanelId());
                bg.setPanelName(box.getPanelName());
                bg.setRoomId(box.getRoomId());
                bg.setRoomName(box.getRoomName());
                bg.setSpec(box.getSpec());
                bg.setZone(box.getZone());
                bg.setUsedCount(0);
                gridList.add(bg);
            }
        }
        boxGridMapper.insertList(gridList);
        return box;
    }


    @Override
    public Box get(Long id) {
        return boxMapper.selectById(id);
    }

    @Override
    public boolean delete(Long id) {
        Box box = new Box();
        box.setIsDelete(1);
        LambdaQueryWrapper<Box> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Box::getId, id);
        return boxMapper.update(box, wrapper) > 0;
    }

    /**
     * @return boolean
     * @Description: updateInfo box basic info
     * @Params: [box]
     * @author wuzhiyu
     * @date 2018/11/15 16:33
     */
    @Override
    public boolean updateInfo(Box box) {
        return boxMapper.updateInfo(box) > 0;
    }

    @Override
    public boolean updateById(Box box) {
        return boxMapper.updateById(box) > 0;
    }

    /**
     * @return java.util.List<com.brillilab.domain.po.reagent.BoxGrid>
     * @Description: get boxgrid list by boxId
     * @Params: [boxId]
     * @author wuzhiyu
     * @date 2018/11/15 18:55
     */
    @Override
    public List<BoxGrid> getGridList(Long boxId) {
        LambdaQueryWrapper<BoxGrid> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BoxGrid::getBoxId, boxId);
        return boxGridMapper.selectList(wrapper);
    }

    @Override
    public List<BoxGridWithReagentType> getBoxGridWithReagentTypeListSpecGtZero(Long labId, Integer zone, Integer size, Integer index) {
        return boxGridMapper.getBoxGridWithReagentTypeList(labId, zone, size, index * size);
    }

    @Override
    public Integer getBoxGridWithReagentTypeListSpecGtZeroCount(Long labId, Integer zone) {
        return boxGridMapper.getBoxGridWithReagentTypeListCount(labId, zone);
    }

    @Override
    public List<BoxGrid> getBoxGridList(Long labId, Integer zone) {
        LambdaQueryWrapper<BoxGrid> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BoxGrid::getLabId, labId);
        wrapper.eq(BoxGrid::getZone, zone);
        wrapper.eq(BoxGrid::getIsFill, IsDeleteEnum.NO);
        wrapper.orderByAsc(BoxGrid::getZone, BoxGrid::getLabMemberId, BoxGrid::getUsedCount);
        return boxGridMapper.selectList(wrapper);
    }

    @Override
    public BoxGrid getBoxGrid(Long gridId) {
        return boxGridMapper.selectById(gridId);
    }

    @Override
    public Integer updateBoxGridFill(List<Long> boxGridIdList, Integer state) {
        return boxGridMapper.updateBoxGridFill(boxGridIdList, state);
    }

    @Override
    public Integer updateBoxGridPosition(Long boxId, BoxGrid boxGrid) {
        LambdaQueryWrapper<BoxGrid> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BoxGrid::getBoxId, boxId);
        return boxGridMapper.update(boxGrid, wrapper);
    }

    @Override
    public List<BoxVo> list(Long panelId) {
        LambdaQueryWrapper<Box> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Box::getPanelId, panelId);
        wrapper.eq(Box::getIsDelete, IsDeleteEnum.NO.getValue());
        LambdaQueryWrapper<PanelGridUsed> wrapperGrid = new LambdaQueryWrapper<>();
        wrapperGrid.eq(PanelGridUsed::getPanelId, panelId);
        wrapperGrid.isNotNull(PanelGridUsed::getBoxId);
        List<PanelGridUsed> gridUsedList = panelGridUsedMapper.selectList(wrapperGrid);
        List<Box> boxList = boxMapper.selectList(wrapper);
        List<BoxVo> voList = new ArrayList<>();
        boxList.forEach(b -> {
            BoxVo bv = new BoxVo();
            MyBeanUtils.copyProperties(b, bv);
            List<PanelGridUsed> usedList = gridUsedList.stream().filter(g -> g.getBoxId().equals(b.getId())).collect(Collectors.toList());
            bv.setPanelGridUsedList(usedList);
            voList.add(bv);
        });
        return voList;
    }

    @Override
    public boolean updateRoomName(Long roomId, String name) {
        Box b = new Box();
        b.setRoomId(roomId);
        b.setRoomName(name);
        LambdaQueryWrapper<Box> query = new LambdaQueryWrapper();
        query.eq(Box::getRoomId, roomId);
        boxMapper.update(b, query);
        BoxGrid bg = new BoxGrid();
        bg.setRoomId(roomId);
        bg.setRoomName(name);
        LambdaQueryWrapper<BoxGrid> queryBg = new LambdaQueryWrapper<>();
        queryBg.eq(BoxGrid::getRoomId, roomId);
        boxGridMapper.update(bg, queryBg);
        return true;
    }

    @Override
    public List<Box> getLabBoxList(Long labId) {
        LambdaQueryWrapper<Box> query = new LambdaQueryWrapper<>();
        query.eq(Box::getLabId, labId);
        query.eq(Box::getIsDelete, IsDeleteEnum.NO.getValue());
        return boxMapper.selectList(query);
    }

    @Override
    public boolean updateGridAndInventoryOwner(Long boxId, Long labMemberId) {
        boxMapper.updateOwner(boxId, labMemberId);
        return true;
    }

    @Override
    public boolean updateBoxAndGridOwnerByPanelId(Long panelId, Long labMemberId) {
        return boxMapper.updateOwnerByPanelId(panelId, labMemberId) > 0;
    }

    @Override
    public List<Box> listByIdList(List<Long> boxIdList) {
        if (CollectionUtils.isEmpty(boxIdList)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Box> query = new LambdaQueryWrapper<>();
        query.in(Box::getId, boxIdList);
        return boxMapper.selectList(query);
    }

    @Override
    public boolean updateInfo(Long boxId, Long labMemberId, String remark, String userReagentType) {
        if (!StringUtils.isEmpty(userReagentType)) {
            if (!userReagentType.startsWith(",")) {
                userReagentType = "," + userReagentType;
            }
            if (!userReagentType.endsWith(",")) {
                userReagentType = userReagentType + ",";
            }
        }
        return boxMapper.updateBoxInfo(boxId, remark, userReagentType, labMemberId) > 0;
    }

    @Override
    public List<Long> getLabSingleBoxIdList(Long labId) {
        return boxMapper.getLabSingleBoxIdList(labId);
    }
}
